//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NMock2;
using Eas.WebCrawler.Interfaces;
using Eas.WebCrawler.PlugIns;

namespace Eas.WebCrawler.Test.Model {
    /// <summary>
    /// Summary description for BaseRequestStoreTest
    /// </summary>
    [TestClass]
    public class BaseRequestStoreTest {

        private static RequestStoreTestContext _Context;
        private static NMock2.Mockery _Mockery;
        private Eas.WebCrawler.Model.Core.BaseRequestStore _Store;
        private string _TempFile;
        private Eas.WebCrawler.PlugIns.RequestComparers.AlphabeticComparer _AlphaComparer = new Eas.WebCrawler.PlugIns.RequestComparers.AlphabeticComparer();
        private string[] NoStartingUris = new string[] { };
        private string[] SimpleStartingUris = new string[] { "http://www.msn.com", "http://www.saltwell.com", "http://www.yahoo.com", "http://www.falkowska.com/default.html", "http://www.saltwell.com", "http://www.microsoft.com" };

        public BaseRequestStoreTest() {
            //
            // TODO: Add constructor logic here
            //
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext) 
        //{
        //
        //}
        //
        // Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup() 
        //{
        //                
        //}
        //
        // Use TestInitialize to run code before running each test 
        [TestInitialize()]
        public void MyTestInitialize() {
            TestDirectoryHelper.Setup();
            _TempFile = System.IO.Path.GetTempFileName();
            _Mockery = new NMock2.Mockery();
            _Context = new RequestStoreTestContext();
            _Context.DelegatedContext = _Mockery.NewMock<Eas.WebCrawler.Interfaces.WebCrawlerContext>();

            _Store = new Eas.WebCrawler.Model.Core.BaseRequestStore();
            _Store.Initialize(_Context);
            StartStore();
        }

        private void StartStore() {
            SetContextProperty("StartingUris", NoStartingUris);
            SetContextProperty("RequestPriorityComparer", _AlphaComparer);
            using (Eas.WebCrawler.PlugIns.Histories.AlwaysEmptyRequestHistory history = new Eas.WebCrawler.PlugIns.Histories.AlwaysEmptyRequestHistory()) {
                SetContextProperty("CompletedRequestHistory", history);
                _Context._Events.Fire_Starting();
            }
        }

        // Use TestCleanup to run code after each test has run
        [TestCleanup()]
        public void MyTestCleanup() {
            _Mockery.VerifyAllExpectationsHaveBeenMet();
            _Context._Events.Fire_Stopped();
            _Store = null;

            _Context.Dispose();
            _Context = null;
            _Mockery.Dispose();
            _Mockery = null;
            if (System.IO.File.Exists(_TempFile))
                System.IO.File.Delete(_TempFile);
            TestDirectoryHelper.TearDown();
        }

        //
        #endregion

        private static void SetContextProperty(string propertyName, object val) {
            Expect.Once.On(_Context.DelegatedContext).GetProperty(propertyName).Will(Return.Value(val));
        }

        [TestMethod]
        /// <summary>Executes the SimpleTest test.</summary>
        public void SimpleTest() {
            Assert.IsFalse(_Store.HasRequests);
            Assert.AreEqual<int>(0, _Store.Count);
            Assert.IsTrue(_Store.AddRequest(RequestHelper.rGoogle));
            Assert.IsTrue(_Store.HasRequests);
            Assert.AreEqual<int>(1, _Store.Count);
            Assert.AreEqual<Request>(RequestHelper.rGoogle, _Store.PopRequest());

            Assert.IsFalse(_Store.HasRequests);
            Assert.AreEqual<int>(0, _Store.Count);

            //Assert.AreSame(_AlphaComparer, _Store.RequestSorter);
        }

        [TestMethod]
        /// <summary>Executes the TestEmptyRequest test.</summary>
        public void TestEmptyRequest() {
            Assert.IsFalse(_Store.AddRequest("", null));
            Assert.IsFalse(_Store.AddRequest(string.Empty, RequestHelper.rGoogle));
            Assert.AreEqual<int>(0, _Store.Count);
        }

        [TestMethod]
        /// <summary>Executes the SimpleUriTest test.</summary>
        public void SimpleUriTest() {
            Assert.IsFalse(_Store.HasRequests);
            Assert.AreEqual<int>(0, _Store.Count);
            Assert.IsTrue(_Store.AddRequest(new Uri("http://www.google.com"), null));
            Assert.IsTrue(_Store.HasRequests);
            Assert.AreEqual<int>(1, _Store.Count);
            Assert.AreEqual<Request>(RequestHelper.rGoogle, _Store.PopRequest());

            Assert.IsFalse(_Store.HasRequests);
            Assert.AreEqual<int>(0, _Store.Count);

            //Assert.AreSame(_AlphaComparer, _Store.RequestSorter);
            Assert.IsNull(_Store.PopRequest());
        }


        [TestMethod]
        /// <summary>Executes the TestSorting test.</summary>
        public void TestSorting() {
            Request a = new Request("a.aspx", RequestHelper.rGoogle);
            Request b = new Request("b.aspx", RequestHelper.rGoogle);
            Request c = new Request("c.aspx", RequestHelper.rGoogle);
            Request d = new Request("d.aspx", RequestHelper.rGoogle);
            Request e = new Request("e.aspx", RequestHelper.rGoogle);
            Request f = new Request("f.aspx", RequestHelper.rGoogle);
            Request g = new Request("g.aspx", RequestHelper.rGoogle);
            Request h = new Request("h.aspx", RequestHelper.rGoogle);
            Request i = new Request("i.aspx", RequestHelper.rGoogle);
            Request j = new Request("j.aspx", RequestHelper.rGoogle);
            Request k = new Request("k.aspx", RequestHelper.rGoogle);
            Request l = new Request("l.aspx", RequestHelper.rGoogle);
            Request m = new Request("m.aspx", RequestHelper.rGoogle);
            Request n = new Request("n.aspx", RequestHelper.rGoogle);
            Request o = new Request("o.aspx", RequestHelper.rGoogle);
            Request p = new Request("p.aspx", RequestHelper.rGoogle);
            Request q = new Request("q.aspx", RequestHelper.rGoogle);
            Request r = new Request("r.aspx", RequestHelper.rGoogle);
            Request s = new Request("s.aspx", RequestHelper.rGoogle);
            Request t = new Request("t.aspx", RequestHelper.rGoogle);
            Request u = new Request("u.aspx", RequestHelper.rGoogle);
            Request v = new Request("v.aspx", RequestHelper.rGoogle);
            Request w = new Request("w.aspx", RequestHelper.rGoogle);
            Request x = new Request("x.aspx", RequestHelper.rGoogle);
            Request y = new Request("y.aspx", RequestHelper.rGoogle);
            Request z = new Request("z.aspx", RequestHelper.rGoogle);


            _Store.AddRequest(RequestHelper.rYahoo);
            _Store.AddRequest(RequestHelper.rGoogle);
            _Store.AddRequest(RequestHelper.rPartial);
            _Store.AddRange(GetAlphabetRequestStrings());

            Assert.AreEqual<int>(29, _Store.Count);
            Assert.AreEqual<Request>(RequestHelper.rGoogle, _Store.PopRequest());
            Assert.AreEqual<Request>(a, _Store.PopRequest());
            Assert.AreEqual<Request>(b, _Store.PopRequest());
            Assert.AreEqual<Request>(c, _Store.PopRequest());
            Assert.AreEqual<Request>(d, _Store.PopRequest());
            Assert.AreEqual<Request>(RequestHelper.rPartial, _Store.PopRequest());
            Assert.AreEqual<Request>(e, _Store.PopRequest());
            Assert.AreEqual<Request>(f, _Store.PopRequest());
            Assert.AreEqual<Request>(g, _Store.PopRequest());
            Assert.AreEqual<Request>(h, _Store.PopRequest());
            Assert.AreEqual<Request>(i, _Store.PopRequest());
            Assert.AreEqual<Request>(j, _Store.PopRequest());
            Assert.AreEqual<Request>(k, _Store.PopRequest());
            Assert.AreEqual<Request>(l, _Store.PopRequest());
            Assert.AreEqual<Request>(m, _Store.PopRequest());
            Assert.AreEqual<Request>(n, _Store.PopRequest());
            Assert.AreEqual<Request>(o, _Store.PopRequest());
            Assert.AreEqual<Request>(p, _Store.PopRequest());
            Assert.AreEqual<Request>(q, _Store.PopRequest());
            Assert.AreEqual<Request>(r, _Store.PopRequest());
            Assert.AreEqual<Request>(s, _Store.PopRequest());
            Assert.AreEqual<Request>(t, _Store.PopRequest());
            Assert.AreEqual<Request>(u, _Store.PopRequest());
            Assert.AreEqual<Request>(v, _Store.PopRequest());
            Assert.AreEqual<Request>(w, _Store.PopRequest());
            Assert.AreEqual<Request>(x, _Store.PopRequest());
            Assert.AreEqual<Request>(y, _Store.PopRequest());
            Assert.AreEqual<Request>(z, _Store.PopRequest());
            Assert.AreEqual<Request>(RequestHelper.rYahoo, _Store.PopRequest());
            Assert.AreEqual<int>(0, _Store.Count);
        }

        [TestMethod]
        /// <summary>Executes the TestDupes test.</summary>
        public void TestDupes() {
            _Store.AddRequest(RequestHelper.rYahoo);
            _Store.AddRequest(RequestHelper.rYahoo);
            Assert.AreEqual<int>(1, _Store.Count);
            Assert.AreEqual<Request>(RequestHelper.rYahoo, _Store.PopRequest());
            Assert.AreEqual<int>(0, _Store.Count);
            Assert.IsFalse(_Store.HasRequests);

            _Store.AddRequest(RequestHelper.rGoogle.Uri.ToString(), null);
            _Store.AddRequest("default.aspx", RequestHelper.rGoogle);
            Assert.AreEqual<int>(2, _Store.Count);
            Assert.AreEqual<Request>(RequestHelper.rGoogle, _Store.PopRequest());
            Assert.AreEqual<Request>(RequestHelper.rPartial, _Store.PopRequest());
            Assert.AreEqual<int>(0, _Store.Count);
            Assert.IsFalse(_Store.HasRequests);
        }

        [TestMethod]
        /// <summary>Executes the TestNoComparer test.</summary>
        public void TestNoComparer() {
            _Context._Events.Fire_Stopped();
            StartStore();
            TestSorting();
        }

        [TestMethod]
        /// <summary>Executes the TestAddingEmptyString test.</summary>
        public void TestAddingEmptyString() {
            string nString = null;
            Assert.IsFalse(_Store.AddRequest("", null));
            Assert.IsFalse(_Store.AddRequest(nString, null));
            Assert.IsTrue(_Store.AddRequest(RequestHelper.rGoogle));
            Assert.IsFalse(_Store.AddRequest("", null));
            Assert.IsFalse(_Store.AddRequest(nString, null));
            Assert.AreEqual<int>(1, _Store.Count);
            Assert.AreEqual<Request>(RequestHelper.rGoogle, _Store.PopRequest());
        }


        [TestMethod]
        /// <summary>Executes the TestWithHistory test.</summary>
        public void TestWithHistory() {
            //private string[] SimpleStartingUris = new string[] {"http://www.msn.com", "http://www.saltwell.com", "http://www.yahoo.com", "http://www.falkowska.com/default.html", "http://www.saltwell.com", "http://www.microsoft.com"};
            Assert.IsTrue(_Store.AddRequest(RequestHelper.rGoogle.ToString(), null));
            _Context._Events.Fire_Stopped();
            SetContextProperty("RequestPriorityComparer", _AlphaComparer);
            using (Eas.WebCrawler.PlugIns.Histories.FileBasedRequestHistory history = new Eas.WebCrawler.PlugIns.Histories.FileBasedRequestHistory(TestDirectoryHelper.Name(TestDirectory.Source, "Uris.txt"))) {
                SetContextProperty("CompletedRequestHistory", history);
                SetContextProperty("StartingUris", SimpleStartingUris);
                _Context._Events.Fire_Starting();
                Assert.AreEqual<int>(2, _Store.Count);
                Assert.AreEqual<Request>(new Request("http://www.falkowska.com/default.html"), _Store.PopRequest());
                Assert.AreEqual<Request>(new Request("http://www.saltwell.com"), _Store.PopRequest());
                Assert.AreEqual<int>(0, _Store.Count);
                Assert.IsFalse(_Store.HasRequests);
            }
        }

        [TestMethod]
        /// <summary>Executes the TestWithHistoryNoForcedAdd test.</summary>
        public void TestWithHistoryNoForcedAdd() {
            //private string[] SimpleStartingUris = new string[] {"http://www.msn.com", "http://www.saltwell.com", "http://www.yahoo.com", "http://www.falkowska.com/default.html", "http://www.saltwell.com", "http://www.microsoft.com"};
            Assert.IsTrue(_Store.AddRequest(RequestHelper.rGoogle.ToString(), null));
            _Context._Events.Fire_Stopped();
            SetContextProperty("RequestPriorityComparer", _AlphaComparer);
            using (Eas.WebCrawler.PlugIns.Histories.FileBasedRequestHistory history = new Eas.WebCrawler.PlugIns.Histories.FileBasedRequestHistory(TestDirectoryHelper.Name(TestDirectory.Source, "Uris.txt"))) {
                SetContextProperty("CompletedRequestHistory", history);
                SetContextProperty("StartingUris", SimpleStartingUris);
                _Context._Events.Fire_Starting();
                _Store.AddRequest(RequestHelper.rMSN);
                Assert.AreEqual<int>(2, _Store.Count);
                Assert.AreEqual<Request>(new Request("http://www.falkowska.com/default.html"), _Store.PopRequest());
                Assert.AreEqual<Request>(new Request("http://www.saltwell.com"), _Store.PopRequest());
                Assert.AreEqual<int>(0, _Store.Count);
                Assert.IsFalse(_Store.HasRequests);
            }
        }

        [TestMethod]
        /// <summary>Executes the TestWithHistoryForcedAdd test.</summary>
        public void TestWithHistoryForcedAdd() {
            //private string[] SimpleStartingUris = new string[] {"http://www.msn.com", "http://www.saltwell.com", "http://www.yahoo.com", "http://www.falkowska.com/default.html", "http://www.saltwell.com", "http://www.microsoft.com"};
            Assert.IsTrue(_Store.AddRequest(RequestHelper.rGoogle.ToString(), null));
            _Context._Events.Fire_Stopped();
            SetContextProperty("RequestPriorityComparer", _AlphaComparer);
            using (Eas.WebCrawler.PlugIns.Histories.FileBasedRequestHistory history = new Eas.WebCrawler.PlugIns.Histories.FileBasedRequestHistory(TestDirectoryHelper.Name(TestDirectory.Source, "Uris.txt"))) {
                SetContextProperty("CompletedRequestHistory", history);
                SetContextProperty("StartingUris", SimpleStartingUris);
                _Context._Events.Fire_Starting();
                _Store.AddPriorityRequest(RequestHelper.rMSN);
                Assert.AreEqual<int>(3, _Store.Count);
                Assert.AreEqual<Request>(RequestHelper.rMSN, _Store.PopRequest());
                Assert.AreEqual<Request>(new Request("http://www.falkowska.com/default.html"), _Store.PopRequest());
                Assert.AreEqual<Request>(new Request("http://www.saltwell.com"), _Store.PopRequest());
                Assert.AreEqual<int>(0, _Store.Count);
                Assert.IsFalse(_Store.HasRequests);
            }
        }

        private static IEnumerable<string> GetAlphabetRequestStrings() {
            yield return "http://www.google.com/a.aspx";
            yield return "http://www.google.com/b.aspx";
            yield return "http://www.google.com/c.aspx";
            yield return "http://www.google.com/d.aspx";
            yield return "http://www.google.com/e.aspx";
            yield return "http://www.google.com/g.aspx";
            yield return "http://www.google.com/f.aspx";
            yield return "http://www.google.com/h.aspx";
            yield return "http://www.google.com/i.aspx";
            yield return "http://www.google.com/j.aspx";
            yield return "http://www.google.com/k.aspx";
            yield return "http://www.google.com/l.aspx";
            yield return "http://www.google.com/m.aspx";
            yield return "http://www.google.com/n.aspx";
            yield return "http://www.google.com/o.aspx";
            yield return "http://www.google.com/p.aspx";
            yield return "http://www.google.com/q.aspx";
            yield return "http://www.google.com/r.aspx";
            yield return "";
            yield return "http://www.google.com/s.aspx";
            yield return "http://www.google.com/t.aspx";
            yield return "http://www.google.com/u.aspx";
            yield return "http://www.google.com/u.aspx";
            yield return "http://www.google.com/u.aspx";
            yield return "http://www.google.com/u.aspx";
            yield return "http://www.google.com/v.aspx";
            yield return "http://www.google.com/w.aspx";
            yield return "http://www.google.com/x.aspx";
            yield return "http://www.google.com/y.aspx";
            yield return "http://www.google.com/z.aspx";

        }

        private static IEnumerable<Request> GetAlphabetRequests() {
            Request a = new Request("a.aspx", RequestHelper.rGoogle);
            Request b = new Request("b.aspx", RequestHelper.rGoogle);
            Request c = new Request("c.aspx", RequestHelper.rGoogle);
            Request d = new Request("d.aspx", RequestHelper.rGoogle);
            Request e = new Request("e.aspx", RequestHelper.rGoogle);
            Request f = new Request("f.aspx", RequestHelper.rGoogle);
            Request g = new Request("g.aspx", RequestHelper.rGoogle);
            Request h = new Request("h.aspx", RequestHelper.rGoogle);
            Request i = new Request("i.aspx", RequestHelper.rGoogle);
            Request j = new Request("j.aspx", RequestHelper.rGoogle);
            Request k = new Request("k.aspx", RequestHelper.rGoogle);
            Request l = new Request("l.aspx", RequestHelper.rGoogle);
            Request m = new Request("m.aspx", RequestHelper.rGoogle);
            Request n = new Request("n.aspx", RequestHelper.rGoogle);
            Request o = new Request("o.aspx", RequestHelper.rGoogle);
            Request p = new Request("p.aspx", RequestHelper.rGoogle);
            Request q = new Request("q.aspx", RequestHelper.rGoogle);
            Request r = new Request("r.aspx", RequestHelper.rGoogle);
            Request s = new Request("s.aspx", RequestHelper.rGoogle);
            Request t = new Request("t.aspx", RequestHelper.rGoogle);
            Request u = new Request("u.aspx", RequestHelper.rGoogle);
            Request v = new Request("v.aspx", RequestHelper.rGoogle);
            Request w = new Request("w.aspx", RequestHelper.rGoogle);
            Request x = new Request("x.aspx", RequestHelper.rGoogle);
            Request y = new Request("y.aspx", RequestHelper.rGoogle);
            Request z = new Request("z.aspx", RequestHelper.rGoogle);

            yield return (a);
            yield return (z);
            yield return (b);
            yield return (p);
            yield return (c);
            yield return (o);
            yield return (d);
            yield return (n);
            yield return (e);
            yield return (m);
            yield return (f);
            yield return (l);
            yield return (g);
            yield return (k);
            yield return (h);
            yield return (j);
            yield return (q);
            yield return (u);
            yield return (r);
            yield return (t);
            yield return (s);
            yield return (v);
            yield return (y);
            yield return (i);
            yield return (w);
            yield return (x);

        }

    }
}
